package com.yuanxin.baidumap;

import android.content.Context;
import android.os.StrictMode;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.Poi;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Overlay;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.TextureMapView;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.yuanxin.baidumap.ReactMapLocationModule.defaultOption;
import static com.yuanxin.baidumap.ReactMapLocationModule.convertLocationTime;

import androidx.annotation.Nullable;

/**
 * Created by yiyang on 16/3/1.
 */
public class BaiduMapViewManager extends SimpleViewManager<TextureMapView> implements LifecycleEventListener {
    public static final String RCT_CLASS = "RCTBaiduMapView";
    private static String TAG = BaiduMapViewManager.class.getSimpleName();
    public static final int COMMAND_ZOOM_TO_LOCS = 1;
    public static final int COMMAND_START_USERLOCATION = 100;
    public static final int COMMAND_STOP_USERLOCATION = 200;
    public static final int COMMAND_ADDPOINT_ANNOTATION = 300;
    public static final int COMMAND_UPDATEPOINT_ANNOTATION = 400;
    public static final int COMMAND_CHANAGE_MAP_STATES = 500;

    private ReactMapView mMapView;

    private MarkerOnInfoWindowClickListener markerListener;

    private Context mContext;

    private boolean isMapLoaded;

//    private GeoCoder mSearch = null;

    private Marker marker = null;

    private Double latitudezoom;
    private Double longitudezoom;

    private int zoomLevel;

    private Map<String, MarkerOptions> overlayMap;

    @Override
    public String getName() {
        return RCT_CLASS;
    }


    @Override
    protected TextureMapView createViewInstance(final ThemedReactContext themedReactContext) {
        this.mContext = themedReactContext;
        themedReactContext.addLifecycleEventListener(this);
        final TextureMapView view = new TextureMapView(themedReactContext);
        mMapView = new ReactMapView(this, view, themedReactContext.getCurrentActivity());
        view.getMap().setOnMapLoadedCallback(new BaiduMap.OnMapLoadedCallback() {
            @Override
            public void onMapLoaded() {
                BaiduMapViewManager.this.isMapLoaded = true;
                mMapView.onMapLoaded();
            }
        });

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        // 初始化编码转化对象
//        mSearch = GeoCoder.newInstance();
//        mSearch.setOnGetGeoCodeResultListener(this);

        markerListener = new MarkerOnInfoWindowClickListener();
        view.getMap().setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                //将marker所在的经纬度的信息转化成屏幕上的坐标
                final LatLng ll = marker.getPosition();
                LinearLayout baidumap_infowindow = (LinearLayout) LayoutInflater.from(themedReactContext.getCurrentActivity()).inflate(R.layout.info, null);
                TextView name = (TextView) baidumap_infowindow.findViewById(R.id.name);
                TextView subtitle = (TextView) baidumap_infowindow.findViewById(R.id.subtitle);
                name.setText(marker.getTitle());
                if (marker.getExtraInfo() != null) {
                    subtitle.setText(marker.getExtraInfo().getString("subtitle", "-"));
                } else {
                    subtitle.setVisibility(View.GONE);
                }
                InfoWindow mInfoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(baidumap_infowindow), ll, -47, markerListener);
                //显示InfoWindow
                view.getMap().showInfoWindow(mInfoWindow);
                return true;
            }
        });
        overlayMap = new HashMap<>();

        return view;
    }

    private final class MarkerOnInfoWindowClickListener implements InfoWindow.OnInfoWindowClickListener {

        @Override
        public void onInfoWindowClick() {
            //隐藏InfoWindow
            getMapView().getMap().hideInfoWindow();
        }

    }

    public ReactMapView getMapView() {
        return mMapView;
    }

    @ReactProp(name = "showsUserLocation", defaultBoolean = false)
    public void showsUserLocation(TextureMapView mapView, Boolean show) {
        mMapView.setShowsUserLocation(show);
    }

    @ReactProp(name = "gesturesEnabled", defaultBoolean = false)
    public void gesturesEnabled(TextureMapView mapView, Boolean gesturesEnabled) {
        mMapView.getMap().getUiSettings().setAllGesturesEnabled(gesturesEnabled);
    }

    @ReactProp(name = "draggable", defaultBoolean = false)
    public void draggable(TextureMapView mapView, Boolean draggable) {
        mMapView.getMap().getUiSettings().setScrollGesturesEnabled(draggable);
    }

    @ReactProp(name = "showsCompass", defaultBoolean = false)
    public void showsCompass(TextureMapView mapView, Boolean show) {
        mapView.getMap().getUiSettings().setCompassEnabled(show);
    }

    @ReactProp(name = "zoomEnabled", defaultBoolean = true)
    public void setZoomEnabled(TextureMapView mapView, Boolean enable) {
        mapView.getMap().getUiSettings().setZoomGesturesEnabled(enable);
    }

    @ReactProp(name = "rotateEnabled", defaultBoolean = true)
    public void setRotateEnabled(TextureMapView mapView, Boolean enable) {
        mapView.getMap().getUiSettings().setRotateGesturesEnabled(enable);
    }

    @ReactProp(name = "pitchEnabled", defaultBoolean = false)
    public void setTiltGestureEnabled(TextureMapView mapView, Boolean enable) {
//        mapView.getMap().getUiSettings().setTiltGesturesEnabled(enable);
    }

    @ReactProp(name = "scrollEnabled", defaultBoolean = false)
    public void setScrollEnabled(TextureMapView mapView, Boolean enable) {
        mapView.getMap().getUiSettings().setScrollGesturesEnabled(enable);
    }

    @ReactProp(name = "autoZoomToSpan", defaultBoolean = true)
    public void setAutoZoomToSpan(TextureMapView mapView, Boolean enable) {
        this.getMapView().setAutoZoomToSpan(enable);
    }

    @ReactProp(name = "mapCenter")
    public void setAutoZoomToSpan(TextureMapView mapView, ReadableMap mapCenter) {
        if (mapCenter != null) {
            double latitude = mapCenter.getDouble("latitude");
            double longitude = mapCenter.getDouble("longitude");
            LatLng latLng = new LatLng(latitude, longitude);
            MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, zoomLevel);
            this.getMapView().getMap().setMapStatus(mapStatusUpdate);
        }
    }


    @ReactProp(name = "mapType", defaultInt = BaiduMap.MAP_TYPE_NORMAL)
    public void setMapType(TextureMapView mapView, int mapType) {
       // Log.e(TAG, "setMapType: " + mapType);
        mapView.getMap().setMapType(mapType);
    }

    @ReactProp(name = "annotations")
    public void setAnnotations(TextureMapView mapView, @Nullable ReadableArray value) throws Exception {
        if (value == null || value.size() == 0) {
           // Log.e(RCT_CLASS, "Error: no annotation");
            return;
        }

        List<ReactMapMarker> markers = new ArrayList<ReactMapMarker>();
        int size = value.size();
        for (int i = 0; i < size; i++) {
            ReadableMap annotation = value.getMap(i);
            ReactMapMarker marker = new ReactMapMarker(this.mContext);
            marker.buildMarker(annotation);
            markers.add(marker);
        }
        getMapView().getMap().hideInfoWindow();
        getMapView().setMarker(markers);

        if (this.isMapLoaded && this.mMapView.isAutoZoomToSpan()) {
            this.mMapView.zoomToSpan();
        }

    }

    @ReactProp(name = "overlays")
    public void setOverlays(TextureMapView mapView, @Nullable ReadableArray value) throws Exception {
        if (value == null || value.size() == 0) {
            return;
        }

        List<ReactMapOverlay> overlays = new ArrayList<ReactMapOverlay>();
        int size = value.size();
        for (int i = 0; i < size; i++) {
            ReadableMap overlay = value.getMap(i);
            ReactMapOverlay polyline = new ReactMapOverlay(overlay);
            if (polyline.getOptions() != null && polyline.getOptions().getPoints() != null && polyline.getOptions().getPoints().size() > 1) {
                overlays.add(polyline);
            }
        }

        getMapView().setOverlays(overlays);


        if (this.isMapLoaded && this.mMapView.isAutoZoomToSpan()) {
            this.mMapView.zoomToSpan();
        }
    }

    @ReactProp(name = "region")
    public void setRegion(TextureMapView mapView, @Nullable ReadableMap center) {
        if (center != null) {
            double latitude = center.getDouble("latitude");
            double longitude = center.getDouble("longitude");
            MapStatus mapStatus = new MapStatus.Builder()
                    .target(new LatLng(latitude, longitude))
                    .build();
            mapView.getMap().animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));
        }
    }

    @ReactProp(name = "userLocationViewParams")
    public void setUserLocationViewParams(TextureMapView mapView, @Nullable ReadableMap params) {
       // Log.e(TAG, "setUserLocationViewParams: " + params);
        ReactMapMyLocationConfiguration configuration = new ReactMapMyLocationConfiguration(this.mContext);
        configuration.buildConfiguration(params);
        this.mMapView.setConfiguration(configuration);
    }

    /*
    地图放大缩小
     */
    @ReactProp(name = "zoomLevel")
    public void zoomLevel(TextureMapView mapView, int zoomLevel) {
       // Log.e(TAG, "zoomLevel: " + zoomLevel);
        this.zoomLevel = zoomLevel;
        mMapView.setZoomLevel(zoomLevel);
//        LatLng latLng;
//       // Log.e(TAG,"latitudezoom"+latitudezoom+"------latitudeadd----"+latitudeaddpoint);
//        if(latitudezoom != null && longitudezoom != null){
//            latLng = new LatLng(latitudezoom,longitudezoom);
//        } else {
//            latLng = new LatLng(39.920141277903454, 116.49771122856677);
//        }

//        BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.location_icon);
//        OverlayOptions options = new MarkerOptions().position(latLng).icon(bitmap);
//        mapView.getMap().addOverlay(options);

//        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, zoomLevel);
//        mapView.getMap().setMapStatus(mapStatusUpdate);

    }

    /*
    路况
     */
    @ReactProp(name = "trafficEnabled")
    public void trafficEnabled(TextureMapView mapView, boolean trafficEnabled) {
       // Log.e(TAG, "trafficEnabled: " + trafficEnabled);
        mapView.getMap().setTrafficEnabled(trafficEnabled);
    }

    /*
    热力
     */
    @ReactProp(name = "baiduHeatMapEnabled")
    public void baiduHeatMapEnabled(TextureMapView mapView, boolean baiduHeatMapEnabled) {
       // Log.e(TAG, "baiduHeatMapEnabled: " + baiduHeatMapEnabled);
        mapView.getMap().setBaiduHeatMapEnabled(baiduHeatMapEnabled);
    }

    /*
    3D
     */
    @ReactProp(name = "buildingsEnabled")
    public void buildingsEnabled(TextureMapView mapView, boolean buildingsEnabled) {
       // Log.e(TAG, "buildingsEnabled: " + buildingsEnabled);
        mapView.getMap().setBuildingsEnabled(buildingsEnabled);
    }

    /**
     * 根据参数开启GPS定位
     */
    public void startUserLocation(ReadableArray startUserLocation) {
       // Log.e(TAG, "startUserLocation---" + startUserLocation);
        getMapView().startLocationServer();
    }

    /*
   添加瞄点
     */
    public void addPointAnnotation(ReadableArray addPointAnnotation) {
//       // Log.e(TAG, "addPointAnnotation---" + addPointAnnotation);
//        ReadableMap annotation = addPointAnnotation.getMap(0);
//        BaiduMap baiduMap = mMapView.getMap();
//        try {
//            ReactMapMarker marker = new ReactMapMarker(this.mContext);
//            MarkerOptions options = marker.buildMarker(annotation);
//            baiduMap.addOverlay(options);
//            MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(options.getPosition(), zoomLevel);
//            baiduMap.setMapStatus(mapStatusUpdate);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
       // Log.e(TAG, "addPointAnnotation---" + addPointAnnotation);
        ReadableMap map = addPointAnnotation.getMap(0);

        String subtile = null, title = null, id = null;
        int image = 0;
        Double latitudeaddpoint = null, longitudeaddpoint = null;

        if (map.hasKey("subtile")) {
            subtile = map.getString("subtile");
           // Log.e(TAG, "addPointAnnotation" + "-subtile-" + subtile);
        }
        if (map.hasKey("longitude")) {
            longitudeaddpoint = map.getDouble("longitude");
           // Log.e(TAG, "addPointAnnotation" + "-longitudeaddpoint-" + longitudeaddpoint);
        }
        if (map.hasKey("title")) {
            title = map.getString("title");
           // Log.e(TAG, "addPointAnnotation" + "-title-" + title);
        }
        if (map.hasKey("latitude")) {
            latitudeaddpoint = map.getDouble("latitude");
           // Log.e(TAG, "addPointAnnotation" + "-latitudeaddpoint-" + latitudeaddpoint);
        }
        if (map.hasKey("image")) {
            image = map.getInt("image");
           // Log.e(TAG, "addPointAnnotation" + "-image-" + image);
        }
        if (map.hasKey("id")) {
            id = map.getString("id");
           // Log.e(TAG, "addPointAnnotation" + "-id-" + id);
        }
        BaiduMap baiduMap = mMapView.getMap();
        LatLng latLng = new LatLng(latitudeaddpoint, longitudeaddpoint);

        if (!overlayMap.containsKey(id)) {

            BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.location);
            MarkerOptions options = new MarkerOptions().position(latLng).icon(bitmap);
            baiduMap.addOverlay(options);
            overlayMap.put(id, options);

        }

        if (overlayMap.size() == 1) {
            MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, zoomLevel);
            baiduMap.setMapStatus(mapStatusUpdate);
        } else {
            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            Collection<MarkerOptions> valueCollection = overlayMap.values();
            for (MarkerOptions options : new ArrayList<MarkerOptions>(valueCollection)) {
                builder.include(options.getPosition());
            }
            MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngBounds(builder.build());
            baiduMap.setMapStatus(mapStatusUpdate);
        }


       // Log.e(TAG, "addPointAnnotation--array-" + "-subtile-" + subtile + "-longitude-" + longitudeaddpoint
//                + "-title-" + title + "-latitude-" + latitudeaddpoint + "-image-" + image + "-id-" + id);
    }

    /**
     * 停止定位
     */
    public void stopUserLocation(ReadableArray stopUserLocation) {
        getMapView().stopLocationServer();
    }

    /*
    改变瞄点
     */
    public void updatePointAnnotation(ReadableArray updatePointAnnotation) {
       // Log.e(TAG, "updatePointAnnotation---" + updatePointAnnotation);
        ReadableMap map = updatePointAnnotation.getMap(0);

        String subtile = null, title = null, id = null;
        int image = 0;
        Double latitudeaddpoint = null, longitudeaddpoint = null;

        if (map.hasKey("subtile")) {
            subtile = map.getString("subtile");
           // Log.e(TAG, "addPointAnnotation" + "-subtile-" + subtile);
        }
        if (map.hasKey("longitude")) {
            longitudeaddpoint = map.getDouble("longitude");
           // Log.e(TAG, "addPointAnnotation" + "-longitudeaddpoint-" + longitudeaddpoint);
        }
        if (map.hasKey("title")) {
            title = map.getString("title");
           // Log.e(TAG, "addPointAnnotation" + "-title-" + title);
        }
        if (map.hasKey("latitude")) {
            latitudeaddpoint = map.getDouble("latitude");
           // Log.e(TAG, "addPointAnnotation" + "-latitudeaddpoint-" + latitudeaddpoint);
        }
        if (map.hasKey("image")) {
            image = map.getInt("image");
           // Log.e(TAG, "addPointAnnotation" + "-image-" + image);
        }
        if (map.hasKey("id")) {
            id = map.getString("id");
           // Log.e(TAG, "addPointAnnotation" + "-id-" + id);
        }

        BaiduMap baiduMap = mMapView.getMap();
        LatLng latLng = new LatLng(latitudeaddpoint, longitudeaddpoint);
        if (overlayMap.containsKey(id)) {
            BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.location);
            MarkerOptions options = new MarkerOptions().position(latLng).icon(bitmap);
            overlayMap.put(id, options);

            Collection<MarkerOptions> valueCollection = overlayMap.values();

            List<OverlayOptions> valueList = new ArrayList<OverlayOptions>(valueCollection);
            baiduMap.clear();
            baiduMap.addOverlays(valueList);
        } else {
            BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.location);
            MarkerOptions options = new MarkerOptions().position(latLng).icon(bitmap);
            baiduMap.addOverlay(options);
            overlayMap.put(id, options);
        }
        if (overlayMap.size() == 1) {
            MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, zoomLevel);
            baiduMap.setMapStatus(mapStatusUpdate);
        } else {
            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            Collection<MarkerOptions> valueCollection = overlayMap.values();
            for (MarkerOptions options : new ArrayList<MarkerOptions>(valueCollection)) {
                builder.include(options.getPosition());
            }
            MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngBounds(builder.build());
            baiduMap.setMapStatus(mapStatusUpdate);
        }
       // Log.e(TAG, "updatePointAnnotation--array-" + "-subtile-" + subtile + "-longitude-" + longitudeaddpoint
//                + "-title-" + title + "-latitude-" + latitudeaddpoint + "-image-" + image + "-id-" + id);
    }

    /**
     * 修改百度地图的状态
     */
    public void chanageMapStates(ReadableArray chanageMapStates) {
       // Log.e(TAG, "chanageMapStates---" + chanageMapStates);
    }

    @Override
    public void receiveCommand(TextureMapView root, int commandId, @Nullable ReadableArray args) {
        switch (commandId) {
            case COMMAND_ZOOM_TO_LOCS:
                List<LatLng> positions = new ArrayList<LatLng>();
                boolean isRegionChange = false;
                if (args != null) {
                    if (args.size() > 0) {
                        if (args.getType(0) == ReadableType.Array) {
                            ReadableArray points = args.getArray(0);
                            positions = retreiveLocsFromArray(points);
                        }
                    }
                    if (args.size() > 1) {
                        if (args.getType(1) == ReadableType.Boolean) {
                            isRegionChange = args.getBoolean(1);
                        }
                    }
                }
               // Log.e(TAG, "COMMAND_ZOOM_TO_LOCS-----" + args);
                this.zoomToLatLngs(root, positions, isRegionChange);
                break;
            case COMMAND_START_USERLOCATION:
                startUserLocation(args);
                break;
            case COMMAND_STOP_USERLOCATION:
                stopUserLocation(args);
                break;
            case COMMAND_ADDPOINT_ANNOTATION:
                addPointAnnotation(args);
                //addPointAnnotation---[{"subtile":"hello","longitude":116.498113,"title":"start","latitude":39.921089,"image":3,"id":"TEST_userPoint"}]
                break;
            case COMMAND_UPDATEPOINT_ANNOTATION:
                updatePointAnnotation(args);
                break;
            case COMMAND_CHANAGE_MAP_STATES:
                chanageMapStates(args);
                break;
            default:
                break;
        }
    }

    @javax.annotation.Nullable
    @Override
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of(
                "zoomToLocs", COMMAND_ZOOM_TO_LOCS,
                "startUserLocation", COMMAND_START_USERLOCATION,
                "stopUserLocation", COMMAND_STOP_USERLOCATION,
                "addPointAnnotation", COMMAND_ADDPOINT_ANNOTATION,
                "updatePointAnnotation", COMMAND_UPDATEPOINT_ANNOTATION,
                "chanageMapStates", COMMAND_CHANAGE_MAP_STATES
        );
    }

    private void zoomToCenter(TextureMapView mapView, LatLng center) {
        mapView.getMap().animateMapStatus(MapStatusUpdateFactory.newLatLngZoom(center, 18));
    }

    private void zoomToLatLngs(TextureMapView mapView, List<LatLng> array) {
        if (array == null || array.size() == 0) {
            this.getMapView().zoomToSpan();
        } else if (array.size() == 1) {
            this.zoomToCenter(mapView, array.get(0));
        } else {
            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            for (LatLng item :
                    array) {
                builder.include(item);
            }
            mapView.getMap().animateMapStatus(MapStatusUpdateFactory.newLatLngBounds(builder.build()));
        }
    }

    /**
     * @param mapView
     * @param array
     * @param isRegionChange 是否通知js坐标刷新
     */
    private void zoomToLatLngs(TextureMapView mapView, List<LatLng> array, boolean isRegionChange) {
        this.zoomToLatLngs(mapView, array);
        if (isRegionChange && array != null && array.size() == 1) {
            onChange(getMapView(), array.get(0).latitude, array.get(0).longitude);
        }
    }

    private static List<LatLng> retreiveLocsFromArray(ReadableArray array) {
        List<LatLng> results = new ArrayList<LatLng>();
        if (array != null && array.size() > 0) {
            int size = array.size();
            for (int i = 0; i < size; i++) {
                if (array.getType(i) != ReadableType.Map && array.getType(i) != ReadableType.Array) {
                    return new ArrayList<LatLng>();
                }
                if (array.getType(i) == ReadableType.Array) {
                    ReadableArray onePointArray = array.getArray(i);
                    if (onePointArray != null && onePointArray.size() == 2) {
                        Double latitude = extractDouble(onePointArray, 0);
                        Double longitude = extractDouble(onePointArray, 1);
                        if (latitude != null && longitude != null) {
                            results.add(new LatLng(latitude, longitude));
                        }
                    }
                } else {
                    ReadableMap onePointMap = array.getMap(i);
                    if (onePointMap != null && onePointMap.hasKey("latitude") && onePointMap.hasKey("longitude")) {
                        Double latitude = extractDouble(onePointMap, "latitude");
                        Double longitude = extractDouble(onePointMap, "longitude");
                        if (latitude != null && longitude != null) {
                            results.add(new LatLng(latitude, longitude));
                        }
                    }
                }
            }
        }

        return results;
    }

    private static Double extractDouble(ReadableArray onePointArray, int arrayIndex) {
        if (arrayIndex >= onePointArray.size() || arrayIndex < 0) {
            return null;
        }
        Double latitude = null;
        if (onePointArray.getType(arrayIndex) == ReadableType.Number) {
            latitude = onePointArray.getDouble(arrayIndex);
        } else if (onePointArray.getType(arrayIndex) == ReadableType.String) {
            latitude = Double.valueOf(onePointArray.getString(arrayIndex));
        }

        return latitude;
    }

    private static Double extractDouble(ReadableMap onePointMap, String mapKey) {
        if (onePointMap == null || !onePointMap.hasKey(mapKey)) {
            return null;
        }
        Double result = null;
        if (onePointMap.getType(mapKey) == ReadableType.Number) {
            result = onePointMap.getDouble(mapKey);
        } else if (onePointMap.getType(mapKey) == ReadableType.String) {
            result = Double.valueOf(onePointMap.getString(mapKey));
        }

        return result;
    }

    boolean isMove = false;

    @Override
    protected void addEventEmitters(final ThemedReactContext reactContext, final TextureMapView view) {
        view.getMap().setOnMapTouchListener(new BaiduMap.OnMapTouchListener() {
            @Override
            public void onTouch(MotionEvent motionEvent) {
                isMove = true;
            }
        });
        // 监听地图移动事件
        view.getMap().setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {

            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus) {
            }

            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus, int i) {

            }

            @Override
            public void onMapStatusChange(MapStatus mapStatus) {
                /*changeLng = mapStatus.target;
               // Log.e(TAG, "latitude--2-" + changeLng.latitude + "---longitude---" + changeLng.longitude);
                view.getMap().clear();
                BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.pin_red);
                OverlayOptions options = new MarkerOptions().position(changeLng).icon(bitmap);
                view.getMap().addOverlay(options);*/
            }

            @Override
            public void onMapStatusChangeFinish(MapStatus mapStatus) {
               // Log.e(TAG, "onMapStatusChangeFinish--latitude-" + mapStatus.target.latitude + "---longitude---" + mapStatus.target.longitude);
                if (isMove) {
                    onChange(getMapView(), mapStatus.target.latitude, mapStatus.target.longitude);
                    isMove = false;
                }

               /* finishLng = mapStatus.target;
                latitudezoom = finishLng.latitude;
                longitudezoom = finishLng.longitude;
               // Log.e(TAG, "latitude--3-" + finishLng.latitude + "---longitude---" + finishLng.longitude);
                if (startLng.latitude != finishLng.latitude
                        || startLng.longitude != finishLng.longitude) {
                    Projection ject = view.getMap().getProjection();
                    Point startPoint = ject.toScreenLocation(startLng);
                    Point finishPoint = ject.toScreenLocation(finishLng);
                    double x = Math.abs(finishPoint.x - startPoint.x);
                    double y = Math.abs(finishPoint.y - startPoint.y);
                    if (x > 1 || y > 1) {
                        List<ReactMapMarker> list = getMapView().getmMarkers();
                        if (list.size() > 0) {
                            ReactMapMarker mk = list.get(0);
                            mk.getMarker().setPosition(finishLng);
                        }
                        getMapView().setMarker(list);
                        mSearch.reverseGeoCode(new ReverseGeoCodeOption()
                                .location(finishLng));
                    }
                     onRegionChangeComplete(mMapView, latitudezoom, longitudezoom);
                }*/
            }
        });
    }

    public void onDidChangeUserLocation(ReactMapView view, BDLocation bdLocation) {
        WritableMap coords = Arguments.createMap();
        coords.putDouble("latitude", bdLocation.getLatitude());
        coords.putDouble("longitude", bdLocation.getLongitude());
        coords.putString("address", bdLocation.getAddrStr());
        coords.putString("country",bdLocation.getCountry());//国家
        coords.putString("countryCode",bdLocation.getCountryCode());//国家编码
        coords.putString("province", bdLocation.getProvince());//省
        coords.putString("city",bdLocation.getCity());//市
        coords.putString("cityCode",bdLocation.getCityCode());//市编码
        coords.putString("district",bdLocation.getDistrict());//区县
        coords.putString("street",bdLocation.getStreet());//街道
        coords.putString("streetNumber",bdLocation.getStreetNumber());//街道号码
        coords.putDouble("accuracy", bdLocation.getRadius());
        coords.putDouble("altitude", bdLocation.getAltitude());
        coords.putInt("altitudeAccuracy", bdLocation.getGpsAccuracyStatus());
        coords.putDouble("heading", bdLocation.getDirection());
        coords.putDouble("speed", bdLocation.getSpeed());
        if (bdLocation.getPoiList() != null && bdLocation.getPoiList().size() > 0) {
            WritableArray array = Arguments.createArray();
            for (Poi p : bdLocation.getPoiList()) {
                WritableMap poi = Arguments.createMap();
                poi.putString("name", p.getName());
                poi.putString("id", p.getId());
                array.pushMap(poi);
            }
            coords.putArray("pois", array);
        }
        WritableMap event = Arguments.createMap();
        event.putMap("coords", coords);
        event.putDouble(" timestamp", convertLocationTime(bdLocation));
       // Log.d(TAG, "location : " + bdLocation.getAddrStr());
        ReactContext reactContext = (ReactContext) view.getView().getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                view.getView().getId(),
                "onDidChangeUserLocation",
                event);
    }


    public void onChange(ReactMapView view, double latitude, double longitude) {
        WritableMap region = Arguments.createMap();
        region.putDouble("latitude", latitude);
        region.putDouble("longitude", longitude);
        WritableMap event = Arguments.createMap();
        event.putMap("region", region);
        ReactContext reactContext = (ReactContext) view.getView().getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                view.getView().getId(),
                "topChange",
                event);
    }

    @javax.annotation.Nullable
    @Override
    public Map getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.of(
                "topChange", MapBuilder.of("registrationName", "onChange"),
                "onDidChangeUserLocation", MapBuilder.of("registrationName", "onDidChangeUserLocation")
        );
    }

    @Override
    public void onDropViewInstance(TextureMapView view) {
        super.onDropViewInstance(view);
        mMapView.stopLocationServer();
        mMapView.getMap().setMyLocationEnabled(false);
    }

    @Override
    public void onHostDestroy() {
        if (mMapView != null)
            mMapView.getView().onDestroy();

    }

    @Override
    public void onHostPause() {
        if (mMapView != null)
            mMapView.getView().onPause();
    }

    @Override
    public void onHostResume() {
        if (mMapView != null)
            mMapView.getView().onResume();
    }
}
